CM3D2 Converter.misc_DATA_PT_modifiers
1# 「プロパティ」エリア → 「モディファイア」タブ 2import os 3import re 4import struct 5import math 6import unicodedata 7import time 8import bpy 9import bmesh 10import mathutils 11from . import common 12from . import compat 13from .translations.pgettext_functions import * 14 15 16# メニュー等に項目追加 17def menu_func(self, context): 18 ob = context.active_object 19 if ob: 20 if ob.type == 'MESH': 21 me = ob.data 22 if len(ob.modifiers): 23 self.layout.operator('object.forced_modifier_apply', icon_value=common.kiss_icon()) 24 25 26@compat.BlRegister() 27class CNV_UL_modifier_selector(common.CNV_UL_generic_selector): 28 bl_label = 'CNV_UL_modifier_selector' 29 bl_options = {'DEFAULT_CLOSED'} 30 bl_region_type = 'WINDOW' 31 bl_space_type = 'PROPERTIES' 32 33 # Constants (flags) 34 # Be careful not to shadow FILTER_ITEM! 35 #bitflag_forced_true = 1 << 0 36 #bitflag_forced_false = 1 << 1 37 #force_values = False 38 #did_force_values = False 39 40 force_values = bpy.props.BoolProperty( 41 name="force_values", 42 default=False, 43 options=set(), 44 ) 45 46 did_force_values = bpy.props.BoolProperty( 47 name="force_values", 48 default=False, 49 options=set(), 50 ) 51 52 # This allows us to have mutually exclusive options, which are also all disable-able! 53 def _gen_force_values(self, context): 54 setattr(self, "force_values", True) 55 setattr(self, "did_force_values", False) 56 print("SET TRUE force_values =", self.force_values) 57 58 def _gen_visible_update(name1, name2): 59 def _u(self, context): 60 self._gen_force_values(context) 61 if (getattr(self, name1)): 62 setattr(self, name2, False) 63 return _u 64 use_filter_viewport_visible = bpy.props.BoolProperty( 65 name="Viewport", 66 default=False, 67 options=set(), 68 description="Only enable modifiers visible in viewport", 69 update=_gen_visible_update("use_filter_viewport_visible", "use_filter_renderer_visible"), 70 ) 71 use_filter_renderer_visible = bpy.props.BoolProperty( 72 name="Renderer", 73 default=False, 74 options=set(), 75 description="Only enable modifiers visible in renderer", 76 update=_gen_visible_update("use_filter_renderer_visible", "use_filter_viewport_visible"), 77 ) 78 use_filter_reversed_visible = bpy.props.BoolProperty( 79 name="Reverse Visible Filter", 80 default=False, 81 options=set(), 82 description="Reverse the selected visible-in filter", 83 update=_gen_force_values 84 ) 85 86 87 use_filter_name_reverse = bpy.props.BoolProperty( 88 name="Reverse Name", 89 default=False, 90 options=set(), 91 description="Reverse name filtering", 92 ) 93 94 def _gen_order_update(name1, name2): 95 def _u(self, ctxt): 96 if (getattr(self, name1)): 97 setattr(self, name2, False) 98 return _u 99 use_order_name = bpy.props.BoolProperty( 100 name="Name", default=False, options=set(), 101 description="Sort groups by their name (case-insensitive)", 102 update=_gen_order_update("use_order_name", "use_order_importance"), 103 ) 104 use_filter_orderby_invert = bpy.props.BoolProperty( 105 name="Order by Invert", 106 default=False, 107 options=set(), 108 description="Invert the sort by order" 109 ) 110 111 112 def draw_filter(self, context, layout): 113 row = layout.row() 114 row.label(text="Visible in:") 115 subrow = row.row(align=True) 116 subrow.prop(self, "use_filter_viewport_visible", toggle=True) 117 subrow.prop(self, "use_filter_renderer_visible", toggle=True) 118 icon = 'ZOOM_OUT' if self.use_filter_reversed_visible else 'ZOOM_IN' 119 icon = compat.icon(icon) 120 subrow.prop(self, "use_filter_reversed_visible", text="", icon=icon) 121 122 super(CNV_UL_modifier_selector, self).draw_filter(context, layout) 123 124 def filter_items(self, context, data, propname): 125 flt_flags, flt_neworder = super(CNV_UL_modifier_selector, self).filter_items(context, data, propname) 126 items = getattr(data, propname) 127 128 if getattr(self, 'did_force_values'): 129 setattr(self,'force_values', False) 130 setattr(self, 'did_force_values', getattr(self, 'force_values')) 131 132 print("CHECK force_values = ", getattr(self, 'force_values')) 133 134 if self.use_filter_viewport_visible or self.use_filter_renderer_visible or getattr(self, 'force_values'): 135 136 if not self.use_filter_reversed_visible: 137 in_flag = self.bitflag_forced_true 138 out_flag = ~(self.bitflag_forced_false | self.bitflag_soft_filter) 139 else: 140 in_flag = self.bitflag_forced_false | self.bitflag_soft_filter 141 out_flag = ~self.bitflag_forced_true 142 143 for index, item in enumerate(items): 144 if getattr(self, 'force_values'): 145 flt_flags[index] |= self.bitflag_forced_value 146 147 if self.use_filter_viewport_visible and item.filter0: 148 flt_flags[index] |= in_flag 149 flt_flags[index] &= out_flag 150 elif self.use_filter_renderer_visible and item.filter1: 151 flt_flags[index] |= in_flag 152 flt_flags[index] &= out_flag 153 elif not self.use_filter_viewport_visible and not self.use_filter_renderer_visible: 154 pass 155 else: 156 flt_flags[index] |= ~out_flag 157 flt_flags[index] &= ~in_flag 158 159 return flt_flags, flt_neworder 160 161 162@compat.BlRegister() 163class CNV_OT_forced_modifier_apply(bpy.types.Operator): 164 bl_idname = 'object.forced_modifier_apply' 165 bl_label = "モディファイア強制適用" 166 bl_description = "シェイプキーのあるメッシュのモディファイアでも強制的に適用します" 167 bl_options = {'REGISTER', 'UNDO'} 168 169 is_preserve_shape_key_values = bpy.props.BoolProperty(name="Preserve Shape Key Values", default=True , description="Ensure shape key values are not changed") 170 171 #is_applies = bpy.props.BoolVectorProperty(name="適用するモディファイア", size=32, options={'SKIP_SAVE'}) 172 is_applies = bpy.props.CollectionProperty(type=common.CNV_SelectorItem) 173 active_modifier = bpy.props.IntProperty(name="Active Modifier") 174 175 apply_viewport_visible = bpy.props.BoolProperty(name="Apply Viewport-Visible Modifiers", default=False) 176 apply_renderer_visible = bpy.props.BoolProperty(name="Apply Renderer-Visible Modifiers", default=False) 177 178 initial_progress = bpy.props.FloatProperty(name="Progress", default=-1, options={'HIDDEN', 'SKIP_SAVE'}) 179 180 181 @classmethod 182 def poll(cls, context): 183 ob = context.active_object 184 return len(ob.modifiers) 185 186 def invoke(self, context, event): 187 ob = context.active_object 188 if len(ob.modifiers) == 0: 189 return {'CANCELLED'} 190 191 for index, mod in enumerate(ob.modifiers): 192 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 193 # self.report(type={'WARNING'}, message="Can only apply the first 32 modifiers at once.") 194 # break 195 icon = 'MOD_%s' % mod.type.replace('DECIMATE','DECIM').replace('SOFT_BODY','SOFT').replace('PARTICLE_SYSTEM','PARTICLES').replace('_SPLIT','SPLIT').replace('_PROJECT','PROJECT').replace('_DEFORM','DEFORM').replace('_SIMULATION','SIM').replace('_EDIT','').replace('_MIX','').replace('_PROXIMITY','').replace('_PAINT','PAINT') 196 icon = compat.icon(icon) 197 198 new_prop = None 199 if index < len(self.is_applies): 200 new_prop = self.is_applies[index] 201 else: 202 new_prop = self.is_applies.add() 203 204 if new_prop.name == mod.name and new_prop.icon == icon: 205 # It's probably the same one, ignore it 206 pass 207 else: 208 new_prop.name = mod.name 209 new_prop.index = index 210 new_prop.value = mod.show_viewport 211 new_prop.preferred = new_prop.value 212 new_prop.icon = icon 213 new_prop.filter0 = mod.show_viewport 214 new_prop.filter1 = mod.show_render 215 216 while len(self.is_applies) > len(ob.modifiers): 217 self.is_applies.remove(len(self.is_applies)-1) 218 219 return context.window_manager.invoke_props_dialog(self) 220 221 def draw(self, context): 222 prefs = common.preferences() 223 if compat.IS_LEGACY: 224 self.layout.prop(prefs, 'custom_normal_blend' , icon=compat.icon('SNAP_NORMAL' ), slider=True) 225 self.layout.prop(self , 'is_preserve_shape_key_values', icon=compat.icon('SHAPEKEY_DATA'), slider=True) 226 self.layout.label(text="適用するモディファイア") 227 ob = context.active_object 228 229 #for index, mod in enumerate(ob.modifiers): 230 # if index >= 32: # luvoid : can only apply 32 modifiers at once. 231 # break 232 # icon = 'MOD_%s' % mod.type.replace('DECIMATE','DECIM').replace('SOFT_BODY','SOFT').replace('PARTICLE_SYSTEM','PARTICLES').replace('_SPLIT','SPLIT').replace('_PROJECT','PROJECT').replace('_DEFORM','DEFORM').replace('_SIMULATION','SIM').replace('_EDIT','').replace('_MIX','').replace('_PROXIMITY','').replace('_PAINT','PAINT') 233 # try: 234 # self.layout.prop(self, 'is_applies', text=mod.name, index=index, icon=icon) 235 # except: 236 # self.layout.prop(self, 'is_applies', text=mod.name, index=index, icon='MODIFIER') 237 238 self.layout.template_list("CNV_UL_modifier_selector", "", self, "is_applies", self, "active_modifier") 239 self.layout.label(text="Show filters", icon='FILE_PARENT') 240 241 def execute(self, context): 242 ob = context.object 243 244 did_start_progress = False 245 if self.initial_progress == -1: 246 progress_start = 0 247 context.window_manager.progress_begin(0, 1) 248 did_start_progress = True 249 else: 250 progress_start = self.initial_progress 251 252 if self.apply_viewport_visible or self.apply_renderer_visible: 253 for index, mod in enumerate(ob.modifiers): 254 new_prop = None 255 if index < len(self.is_applies): 256 new_prop = self.is_applies[index] 257 else: 258 new_prop = self.is_applies.add() 259 260 new_prop.name = mod.name 261 new_prop.index = index 262 new_prop.value = (self.apply_viewport_visible and mod.show_viewport) or (self.apply_renderer_visible and mod.show_render) 263 264 # 対象が一つも無い場合はキャンセル扱いとする 265 is_any = False 266 for item in self.is_applies: 267 if item.value: 268 is_any = True 269 break 270 if not is_any: 271 self.report(type={'INFO'}, message="適用対象のモディファイアがないため、キャンセルします") 272 context.window_manager.progress_update(progress_start + 1) 273 if did_start_progress: 274 context.window_manager.progress_end() 275 return {'CANCELLED'} 276 277 custom_normal_blend = common.preferences().custom_normal_blend 278 bpy.ops.object.mode_set(mode='OBJECT') 279 280 me = ob.data 281 is_shaped = bool(me.shape_keys) 282 283 pre_selected_objects = context.selected_objects[:] 284 pre_mode = ob.mode 285 286 arm_ob = None 287 if compat.IS_LEGACY: 288 for mod in ob.modifiers: 289 if mod.type == "ARMATURE": 290 arm_ob = mod.object 291 292 progress = 0 293 progress_count = 1 294 progress_count += 2 if arm_ob else 0 295 progress_count += len(me.shape_keys.key_blocks) * 3 if is_shaped else 0 296 297 if is_shaped: 298 pre_active_shape_key_index = ob.active_shape_key_index 299 pre_relative_keys = [None] * len(me.shape_keys.key_blocks) 300 pre_shape_key_values = [0] * len(me.shape_keys.key_blocks) 301 shape_names = [""] * len(me.shape_keys.key_blocks) 302 shape_deforms = [None] * len(me.shape_keys.key_blocks) 303 for shape_index, shape in enumerate(me.shape_keys.key_blocks): 304 pre_relative_keys [shape_index] = shape.relative_key.name 305 pre_shape_key_values[shape_index] = shape.value 306 shape_names [shape_index] = shape.name 307 shape_deforms [shape_index] = [shape.data[v.index].co.copy() for v in me.vertices] 308 309 progress += 1 310 context.window_manager.progress_update(progress_start + progress / progress_count) 311 312 ob.active_shape_key_index = len(me.shape_keys.key_blocks) - 1 313 for i in me.shape_keys.key_blocks[:]: 314 ob.shape_key_remove(ob.active_shape_key) 315 316 new_shape_deforms = [] 317 for shape_index, deforms in enumerate(shape_deforms): 318 temp_ob = ob.copy() 319 temp_me = me.copy() 320 temp_ob.data = temp_me 321 compat.link(context.scene, temp_ob) 322 try: 323 for vert in temp_me.vertices: 324 vert.co = deforms[vert.index].copy() 325 326 override = context.copy() 327 override['object'] = temp_ob 328 for index, mod in enumerate(temp_ob.modifiers): 329 if self.is_applies[index].value: 330 try: 331 bpy.ops.object.modifier_apply(override, modifier=mod.name) 332 except: 333 temp_ob.modifiers.remove(mod) 334 335 new_shape_deforms.append([v.co.copy() for v in temp_me.vertices]) 336 except Exception as e: 337 #ob.modifiers.remove(mod) 338 self.report(type={'WARNING'}, message=f_tip_("Could not apply '{}' modifier \"{}\" to shapekey {}", mod.type, mod.name, shape_index)) 339 print(f_("Error applying '{type}' modifier \"{name}\":\n\t", type=mod.type, name=mod.name), e) 340 finally: 341 common.remove_data(temp_ob) 342 common.remove_data(temp_me) 343 344 progress += 1 345 context.window_manager.progress_update(progress_start + progress / progress_count) 346 347 if ob.active_shape_key_index != 0: 348 ob.active_shape_key_index = 0 349 me.update() 350 351 copy_modifiers = ob.modifiers[:] 352 mod_count = len(copy_modifiers) 353 mod_progress = 0 354 override = context.copy() 355 override['object'] = ob 356 for index, mod in enumerate(copy_modifiers): 357 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 358 # break 359 if self.is_applies[index].value and (mod.type != 'ARMATURE' or not compat.IS_LEGACY): 360 if mod.type == 'MIRROR' and mod.use_mirror_vertex_groups: 361 if bpy.ops.object.decode_cm3d2_vertex_group_names.poll(): 362 self.report(type={'WARNING'}, message="Vertex groups are not in blender naming style. Mirror modifier results may not be as expected") 363 for vg in ob.vertex_groups[:]: 364 replace_list = ((r'\.L$', ".R"), (r'\.R$', ".L"), (r'\.l$', ".r"), (r'\.r$', ".l"), (r'_L$', "_R"), (r'_R$', "_L"), (r'_l$', "_r"), (r'_r$', "_l")) 365 for before, after in replace_list: 366 mirrored_name = re.sub(before, after, vg.name) 367 if mirrored_name not in ob.vertex_groups: 368 ob.vertex_groups.new(override, name=mirrored_name) 369 try: 370 bpy.ops.object.modifier_apply(override, modifier=mod.name) 371 except Exception as e: 372 #ob.modifiers.remove(mod) 373 self.report(type={'ERROR', 'WARNING'}, message=f_tip_("Could not apply '{type}' modifier \"{name}\"", type=mod.type, name=mod.name)) 374 print(f_("Error applying '{type}' modifier \"{name}\":\n\t", type=mod.type, name=mod.name), e) 375 376 mod_progress += 1 if (mod.type != 'ARMATURE' or not compat.IS_LEGACY) else 0 377 context.window_manager.progress_update( progress_start + (progress + mod_progress / mod_count) / progress_count ) 378 379 # Calculate custom normals for armature modifiers in legacy blender 380 if arm_ob: 381 bpy.ops.object.mode_set(mode='EDIT') 382 bpy.ops.object.mode_set(mode='OBJECT') 383 384 arm = arm_ob.data 385 arm_pose = arm_ob.pose 386 387 pose_quats = {} 388 for bone in arm.bones: 389 pose_bone = arm_pose.bones[bone.name] 390 391 bone_quat = bone.matrix_local.to_quaternion() 392 pose_quat = pose_bone.matrix.to_quaternion() 393 result_quat = compat.mul(pose_quat, bone_quat.inverted()) 394 395 pose_quats[bone.name] = result_quat.copy() 396 397 custom_normals = [] 398 for loop in me.loops: 399 vert = me.vertices[loop.vertex_index] 400 no = vert.normal.copy() 401 402 total_weight = 0.0 403 for vge in vert.groups: 404 vg = ob.vertex_groups[vge.group] 405 try: 406 pose_quats[vg.name] 407 except KeyError: 408 continue 409 total_weight += vge.weight 410 411 total_quat = mathutils.Quaternion() 412 if total_weight != 0.0: 413 for vge in vert.groups: 414 vg = ob.vertex_groups[vge.group] 415 try: 416 total_quat = total_quat.slerp(pose_quats[vg.name], vge.weight / total_weight) 417 except KeyError: 418 pass 419 420 no.rotate(total_quat) 421 custom_normals.append(no) 422 423 progress += 1 424 context.window_manager.progress_update(progress_start + progress / progress_count) 425 426 override = context.copy() 427 override['object'] = ob 428 for index, mod in enumerate(copy_modifiers): 429 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 430 # break 431 if self.is_applies[index].value and (mod.type == 'ARMATURE' and compat.IS_LEGACY): 432 try: 433 bpy.ops.object.modifier_apply(override, modifier=mod.name) 434 except Exception as e: 435 #ob.modifiers.remove(mod) 436 self.report(type={'ERROR', 'WARNING'}, message=f_tip_("Could not apply '{mod_type}' modifier \"{mod_name}\"", mod_type=mod.type, mod_name=mod.name) ) 437 print(f_("Could not apply '{mod_type}' modifier \"{mod_name}\":\n\t", mod_type=mod.type, mod_name=mod.name), e) 438 439 mod_progress += 1 if (mod.type == 'ARMATURE' and compat.IS_LEGACY) else 0 440 context.window_manager.progress_update( progress_start + (progress + mod_progress / mod_count) / progress_count ) 441 442 progress += 1 443 context.window_manager.progress_update(progress_start + progress / progress_count) 444 445 compat.set_active(context, ob) 446 447 if is_shaped: 448 for deforms in new_shape_deforms: 449 if len(me.vertices) != len(deforms): 450 self.report(type={'ERROR'}, message="ミラー等が原因で頂点数が変わっているためシェイプキーを格納できません、中止するのでCtrl+Z等で元に戻し修正してください。") 451 context.window_manager.progress_update(progress_start + 1) 452 if did_start_progress: 453 context.window_manager.progress_end() 454 return {'FINISHED', 'CANCELLED'} 455 456 for shape_index, deforms in enumerate(new_shape_deforms): 457 bpy.ops.object.shape_key_add(context.copy(), from_mix=False) 458 shape = ob.active_shape_key 459 shape.name = shape_names[shape_index] 460 461 for vert in me.vertices: 462 shape.data[vert.index].co = deforms[vert.index].copy() 463 464 progress += 1 465 context.window_manager.progress_update(progress_start + progress / progress_count) 466 467 for shape_index, shape in enumerate(me.shape_keys.key_blocks): 468 shape.relative_key = me.shape_keys.key_blocks[pre_relative_keys[shape_index]] 469 if self.is_preserve_shape_key_values: 470 shape.value = pre_shape_key_values[shape_index] 471 472 ob.active_shape_key_index = pre_active_shape_key_index 473 474 for temp_ob in pre_selected_objects: 475 compat.set_select(temp_ob, True) 476 bpy.ops.object.mode_set(mode=pre_mode) 477 478 if arm_ob: 479 for i, loop in enumerate(me.loops): 480 vert = me.vertices[loop.vertex_index] 481 no = vert.normal.copy() 482 483 try: 484 custom_rot = mathutils.Vector((0.0, 0.0, 1.0)).rotation_difference(custom_normals[i]) 485 except: 486 continue 487 original_rot = mathutils.Vector((0.0, 0.0, 1.0)).rotation_difference(no) 488 output_rot = original_rot.slerp(custom_rot, custom_normal_blend) 489 490 output_no = mathutils.Vector((0.0, 0.0, 1.0)) 491 output_no.rotate(output_rot) 492 493 custom_normals[i] = output_no 494 me.use_auto_smooth = True 495 me.normals_split_custom_set(custom_normals) 496 497 progress += 1 498 context.window_manager.progress_update(progress_start + progress / progress_count) 499 500 context.window_manager.progress_update(progress_start + 1) 501 if did_start_progress: 502 context.window_manager.progress_end() 503 return {'FINISHED'}
@compat.BlRegister()
class
CNV_UL_modifier_selector27@compat.BlRegister() 28class CNV_UL_modifier_selector(common.CNV_UL_generic_selector): 29 bl_label = 'CNV_UL_modifier_selector' 30 bl_options = {'DEFAULT_CLOSED'} 31 bl_region_type = 'WINDOW' 32 bl_space_type = 'PROPERTIES' 33 34 # Constants (flags) 35 # Be careful not to shadow FILTER_ITEM! 36 #bitflag_forced_true = 1 << 0 37 #bitflag_forced_false = 1 << 1 38 #force_values = False 39 #did_force_values = False 40 41 force_values = bpy.props.BoolProperty( 42 name="force_values", 43 default=False, 44 options=set(), 45 ) 46 47 did_force_values = bpy.props.BoolProperty( 48 name="force_values", 49 default=False, 50 options=set(), 51 ) 52 53 # This allows us to have mutually exclusive options, which are also all disable-able! 54 def _gen_force_values(self, context): 55 setattr(self, "force_values", True) 56 setattr(self, "did_force_values", False) 57 print("SET TRUE force_values =", self.force_values) 58 59 def _gen_visible_update(name1, name2): 60 def _u(self, context): 61 self._gen_force_values(context) 62 if (getattr(self, name1)): 63 setattr(self, name2, False) 64 return _u 65 use_filter_viewport_visible = bpy.props.BoolProperty( 66 name="Viewport", 67 default=False, 68 options=set(), 69 description="Only enable modifiers visible in viewport", 70 update=_gen_visible_update("use_filter_viewport_visible", "use_filter_renderer_visible"), 71 ) 72 use_filter_renderer_visible = bpy.props.BoolProperty( 73 name="Renderer", 74 default=False, 75 options=set(), 76 description="Only enable modifiers visible in renderer", 77 update=_gen_visible_update("use_filter_renderer_visible", "use_filter_viewport_visible"), 78 ) 79 use_filter_reversed_visible = bpy.props.BoolProperty( 80 name="Reverse Visible Filter", 81 default=False, 82 options=set(), 83 description="Reverse the selected visible-in filter", 84 update=_gen_force_values 85 ) 86 87 88 use_filter_name_reverse = bpy.props.BoolProperty( 89 name="Reverse Name", 90 default=False, 91 options=set(), 92 description="Reverse name filtering", 93 ) 94 95 def _gen_order_update(name1, name2): 96 def _u(self, ctxt): 97 if (getattr(self, name1)): 98 setattr(self, name2, False) 99 return _u 100 use_order_name = bpy.props.BoolProperty( 101 name="Name", default=False, options=set(), 102 description="Sort groups by their name (case-insensitive)", 103 update=_gen_order_update("use_order_name", "use_order_importance"), 104 ) 105 use_filter_orderby_invert = bpy.props.BoolProperty( 106 name="Order by Invert", 107 default=False, 108 options=set(), 109 description="Invert the sort by order" 110 ) 111 112 113 def draw_filter(self, context, layout): 114 row = layout.row() 115 row.label(text="Visible in:") 116 subrow = row.row(align=True) 117 subrow.prop(self, "use_filter_viewport_visible", toggle=True) 118 subrow.prop(self, "use_filter_renderer_visible", toggle=True) 119 icon = 'ZOOM_OUT' if self.use_filter_reversed_visible else 'ZOOM_IN' 120 icon = compat.icon(icon) 121 subrow.prop(self, "use_filter_reversed_visible", text="", icon=icon) 122 123 super(CNV_UL_modifier_selector, self).draw_filter(context, layout) 124 125 def filter_items(self, context, data, propname): 126 flt_flags, flt_neworder = super(CNV_UL_modifier_selector, self).filter_items(context, data, propname) 127 items = getattr(data, propname) 128 129 if getattr(self, 'did_force_values'): 130 setattr(self,'force_values', False) 131 setattr(self, 'did_force_values', getattr(self, 'force_values')) 132 133 print("CHECK force_values = ", getattr(self, 'force_values')) 134 135 if self.use_filter_viewport_visible or self.use_filter_renderer_visible or getattr(self, 'force_values'): 136 137 if not self.use_filter_reversed_visible: 138 in_flag = self.bitflag_forced_true 139 out_flag = ~(self.bitflag_forced_false | self.bitflag_soft_filter) 140 else: 141 in_flag = self.bitflag_forced_false | self.bitflag_soft_filter 142 out_flag = ~self.bitflag_forced_true 143 144 for index, item in enumerate(items): 145 if getattr(self, 'force_values'): 146 flt_flags[index] |= self.bitflag_forced_value 147 148 if self.use_filter_viewport_visible and item.filter0: 149 flt_flags[index] |= in_flag 150 flt_flags[index] &= out_flag 151 elif self.use_filter_renderer_visible and item.filter1: 152 flt_flags[index] |= in_flag 153 flt_flags[index] &= out_flag 154 elif not self.use_filter_viewport_visible and not self.use_filter_renderer_visible: 155 pass 156 else: 157 flt_flags[index] |= ~out_flag 158 flt_flags[index] &= ~in_flag 159 160 return flt_flags, flt_neworder
force_values: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'force_values', 'default': False, 'options': set(), 'attr': 'force_values'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'force_values', 'default': False, 'options': set(), 'attr': 'force_values'}>
did_force_values: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'force_values', 'default': False, 'options': set(), 'attr': 'did_force_values'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'force_values', 'default': False, 'options': set(), 'attr': 'did_force_values'}>
use_filter_viewport_visible: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Viewport', 'default': False, 'options': set(), 'description': 'Only enable modifiers visible in viewport', 'update': <function CNV_UL_modifier_selector._gen_visible_update.<locals>._u at 0x7f6a0eb67e20>, 'attr': 'use_filter_viewport_visible'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Viewport', 'default': False, 'options': set(), 'description': 'Only enable modifiers visible in viewport', 'update': <function CNV_UL_modifier_selector._gen_visible_update.<locals>._u>, 'attr': 'use_filter_viewport_visible'}>
use_filter_renderer_visible: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Renderer', 'default': False, 'options': set(), 'description': 'Only enable modifiers visible in renderer', 'update': <function CNV_UL_modifier_selector._gen_visible_update.<locals>._u at 0x7f6a0eb67eb0>, 'attr': 'use_filter_renderer_visible'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Renderer', 'default': False, 'options': set(), 'description': 'Only enable modifiers visible in renderer', 'update': <function CNV_UL_modifier_selector._gen_visible_update.<locals>._u>, 'attr': 'use_filter_renderer_visible'}>
use_filter_reversed_visible: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Reverse Visible Filter', 'default': False, 'options': set(), 'description': 'Reverse the selected visible-in filter', 'update': <function CNV_UL_modifier_selector._gen_force_values at 0x7f6a0eb67d00>, 'attr': 'use_filter_reversed_visible'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Reverse Visible Filter', 'default': False, 'options': set(), 'description': 'Reverse the selected visible-in filter', 'update': <function CNV_UL_modifier_selector._gen_force_values>, 'attr': 'use_filter_reversed_visible'}>
use_filter_name_reverse: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Reverse Name', 'default': False, 'options': set(), 'description': 'Reverse name filtering', 'attr': 'use_filter_name_reverse'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Reverse Name', 'default': False, 'options': set(), 'description': 'Reverse name filtering', 'attr': 'use_filter_name_reverse'}>
use_order_name: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Name', 'default': False, 'options': set(), 'description': 'Sort groups by their name (case-insensitive)', 'update': <function CNV_UL_modifier_selector._gen_order_update.<locals>._u at 0x7f6a0eba4040>, 'attr': 'use_order_name'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Name', 'default': False, 'options': set(), 'description': 'Sort groups by their name (case-insensitive)', 'update': <function CNV_UL_modifier_selector._gen_order_update.<locals>._u>, 'attr': 'use_order_name'}>
use_filter_orderby_invert: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Order by Invert', 'default': False, 'options': set(), 'description': 'Invert the sort by order', 'attr': 'use_filter_orderby_invert'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Order by Invert', 'default': False, 'options': set(), 'description': 'Invert the sort by order', 'attr': 'use_filter_orderby_invert'}>
def
draw_filter(self, context, layout):
113 def draw_filter(self, context, layout): 114 row = layout.row() 115 row.label(text="Visible in:") 116 subrow = row.row(align=True) 117 subrow.prop(self, "use_filter_viewport_visible", toggle=True) 118 subrow.prop(self, "use_filter_renderer_visible", toggle=True) 119 icon = 'ZOOM_OUT' if self.use_filter_reversed_visible else 'ZOOM_IN' 120 icon = compat.icon(icon) 121 subrow.prop(self, "use_filter_reversed_visible", text="", icon=icon) 122 123 super(CNV_UL_modifier_selector, self).draw_filter(context, layout)
def
filter_items(self, context, data, propname):
125 def filter_items(self, context, data, propname): 126 flt_flags, flt_neworder = super(CNV_UL_modifier_selector, self).filter_items(context, data, propname) 127 items = getattr(data, propname) 128 129 if getattr(self, 'did_force_values'): 130 setattr(self,'force_values', False) 131 setattr(self, 'did_force_values', getattr(self, 'force_values')) 132 133 print("CHECK force_values = ", getattr(self, 'force_values')) 134 135 if self.use_filter_viewport_visible or self.use_filter_renderer_visible or getattr(self, 'force_values'): 136 137 if not self.use_filter_reversed_visible: 138 in_flag = self.bitflag_forced_true 139 out_flag = ~(self.bitflag_forced_false | self.bitflag_soft_filter) 140 else: 141 in_flag = self.bitflag_forced_false | self.bitflag_soft_filter 142 out_flag = ~self.bitflag_forced_true 143 144 for index, item in enumerate(items): 145 if getattr(self, 'force_values'): 146 flt_flags[index] |= self.bitflag_forced_value 147 148 if self.use_filter_viewport_visible and item.filter0: 149 flt_flags[index] |= in_flag 150 flt_flags[index] &= out_flag 151 elif self.use_filter_renderer_visible and item.filter1: 152 flt_flags[index] |= in_flag 153 flt_flags[index] &= out_flag 154 elif not self.use_filter_viewport_visible and not self.use_filter_renderer_visible: 155 pass 156 else: 157 flt_flags[index] |= ~out_flag 158 flt_flags[index] &= ~in_flag 159 160 return flt_flags, flt_neworder
Inherited Members
- CM3D2 Converter.common.CNV_UL_generic_selector
- bitflag_soft_filter
- bitflag_forced_value
- bitflag_forced_true
- bitflag_forced_false
- cached_values
- expanded_layout
- draw_item
- bpy_types._GenericUI
- is_extended
- append
- prepend
- remove
- builtins.bpy_struct
- keys
- values
- items
- get
- pop
- as_pointer
- keyframe_insert
- keyframe_delete
- driver_add
- driver_remove
- is_property_set
- property_unset
- is_property_readonly
- is_property_overridable_library
- property_overridable_library_set
- path_resolve
- path_from_id
- type_recast
- bl_rna_get_subclass_py
- bl_rna_get_subclass
- id_properties_ensure
- id_properties_clear
- id_properties_ui
- id_data
@compat.BlRegister()
class
CNV_OT_forced_modifier_apply163@compat.BlRegister() 164class CNV_OT_forced_modifier_apply(bpy.types.Operator): 165 bl_idname = 'object.forced_modifier_apply' 166 bl_label = "モディファイア強制適用" 167 bl_description = "シェイプキーのあるメッシュのモディファイアでも強制的に適用します" 168 bl_options = {'REGISTER', 'UNDO'} 169 170 is_preserve_shape_key_values = bpy.props.BoolProperty(name="Preserve Shape Key Values", default=True , description="Ensure shape key values are not changed") 171 172 #is_applies = bpy.props.BoolVectorProperty(name="適用するモディファイア", size=32, options={'SKIP_SAVE'}) 173 is_applies = bpy.props.CollectionProperty(type=common.CNV_SelectorItem) 174 active_modifier = bpy.props.IntProperty(name="Active Modifier") 175 176 apply_viewport_visible = bpy.props.BoolProperty(name="Apply Viewport-Visible Modifiers", default=False) 177 apply_renderer_visible = bpy.props.BoolProperty(name="Apply Renderer-Visible Modifiers", default=False) 178 179 initial_progress = bpy.props.FloatProperty(name="Progress", default=-1, options={'HIDDEN', 'SKIP_SAVE'}) 180 181 182 @classmethod 183 def poll(cls, context): 184 ob = context.active_object 185 return len(ob.modifiers) 186 187 def invoke(self, context, event): 188 ob = context.active_object 189 if len(ob.modifiers) == 0: 190 return {'CANCELLED'} 191 192 for index, mod in enumerate(ob.modifiers): 193 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 194 # self.report(type={'WARNING'}, message="Can only apply the first 32 modifiers at once.") 195 # break 196 icon = 'MOD_%s' % mod.type.replace('DECIMATE','DECIM').replace('SOFT_BODY','SOFT').replace('PARTICLE_SYSTEM','PARTICLES').replace('_SPLIT','SPLIT').replace('_PROJECT','PROJECT').replace('_DEFORM','DEFORM').replace('_SIMULATION','SIM').replace('_EDIT','').replace('_MIX','').replace('_PROXIMITY','').replace('_PAINT','PAINT') 197 icon = compat.icon(icon) 198 199 new_prop = None 200 if index < len(self.is_applies): 201 new_prop = self.is_applies[index] 202 else: 203 new_prop = self.is_applies.add() 204 205 if new_prop.name == mod.name and new_prop.icon == icon: 206 # It's probably the same one, ignore it 207 pass 208 else: 209 new_prop.name = mod.name 210 new_prop.index = index 211 new_prop.value = mod.show_viewport 212 new_prop.preferred = new_prop.value 213 new_prop.icon = icon 214 new_prop.filter0 = mod.show_viewport 215 new_prop.filter1 = mod.show_render 216 217 while len(self.is_applies) > len(ob.modifiers): 218 self.is_applies.remove(len(self.is_applies)-1) 219 220 return context.window_manager.invoke_props_dialog(self) 221 222 def draw(self, context): 223 prefs = common.preferences() 224 if compat.IS_LEGACY: 225 self.layout.prop(prefs, 'custom_normal_blend' , icon=compat.icon('SNAP_NORMAL' ), slider=True) 226 self.layout.prop(self , 'is_preserve_shape_key_values', icon=compat.icon('SHAPEKEY_DATA'), slider=True) 227 self.layout.label(text="適用するモディファイア") 228 ob = context.active_object 229 230 #for index, mod in enumerate(ob.modifiers): 231 # if index >= 32: # luvoid : can only apply 32 modifiers at once. 232 # break 233 # icon = 'MOD_%s' % mod.type.replace('DECIMATE','DECIM').replace('SOFT_BODY','SOFT').replace('PARTICLE_SYSTEM','PARTICLES').replace('_SPLIT','SPLIT').replace('_PROJECT','PROJECT').replace('_DEFORM','DEFORM').replace('_SIMULATION','SIM').replace('_EDIT','').replace('_MIX','').replace('_PROXIMITY','').replace('_PAINT','PAINT') 234 # try: 235 # self.layout.prop(self, 'is_applies', text=mod.name, index=index, icon=icon) 236 # except: 237 # self.layout.prop(self, 'is_applies', text=mod.name, index=index, icon='MODIFIER') 238 239 self.layout.template_list("CNV_UL_modifier_selector", "", self, "is_applies", self, "active_modifier") 240 self.layout.label(text="Show filters", icon='FILE_PARENT') 241 242 def execute(self, context): 243 ob = context.object 244 245 did_start_progress = False 246 if self.initial_progress == -1: 247 progress_start = 0 248 context.window_manager.progress_begin(0, 1) 249 did_start_progress = True 250 else: 251 progress_start = self.initial_progress 252 253 if self.apply_viewport_visible or self.apply_renderer_visible: 254 for index, mod in enumerate(ob.modifiers): 255 new_prop = None 256 if index < len(self.is_applies): 257 new_prop = self.is_applies[index] 258 else: 259 new_prop = self.is_applies.add() 260 261 new_prop.name = mod.name 262 new_prop.index = index 263 new_prop.value = (self.apply_viewport_visible and mod.show_viewport) or (self.apply_renderer_visible and mod.show_render) 264 265 # 対象が一つも無い場合はキャンセル扱いとする 266 is_any = False 267 for item in self.is_applies: 268 if item.value: 269 is_any = True 270 break 271 if not is_any: 272 self.report(type={'INFO'}, message="適用対象のモディファイアがないため、キャンセルします") 273 context.window_manager.progress_update(progress_start + 1) 274 if did_start_progress: 275 context.window_manager.progress_end() 276 return {'CANCELLED'} 277 278 custom_normal_blend = common.preferences().custom_normal_blend 279 bpy.ops.object.mode_set(mode='OBJECT') 280 281 me = ob.data 282 is_shaped = bool(me.shape_keys) 283 284 pre_selected_objects = context.selected_objects[:] 285 pre_mode = ob.mode 286 287 arm_ob = None 288 if compat.IS_LEGACY: 289 for mod in ob.modifiers: 290 if mod.type == "ARMATURE": 291 arm_ob = mod.object 292 293 progress = 0 294 progress_count = 1 295 progress_count += 2 if arm_ob else 0 296 progress_count += len(me.shape_keys.key_blocks) * 3 if is_shaped else 0 297 298 if is_shaped: 299 pre_active_shape_key_index = ob.active_shape_key_index 300 pre_relative_keys = [None] * len(me.shape_keys.key_blocks) 301 pre_shape_key_values = [0] * len(me.shape_keys.key_blocks) 302 shape_names = [""] * len(me.shape_keys.key_blocks) 303 shape_deforms = [None] * len(me.shape_keys.key_blocks) 304 for shape_index, shape in enumerate(me.shape_keys.key_blocks): 305 pre_relative_keys [shape_index] = shape.relative_key.name 306 pre_shape_key_values[shape_index] = shape.value 307 shape_names [shape_index] = shape.name 308 shape_deforms [shape_index] = [shape.data[v.index].co.copy() for v in me.vertices] 309 310 progress += 1 311 context.window_manager.progress_update(progress_start + progress / progress_count) 312 313 ob.active_shape_key_index = len(me.shape_keys.key_blocks) - 1 314 for i in me.shape_keys.key_blocks[:]: 315 ob.shape_key_remove(ob.active_shape_key) 316 317 new_shape_deforms = [] 318 for shape_index, deforms in enumerate(shape_deforms): 319 temp_ob = ob.copy() 320 temp_me = me.copy() 321 temp_ob.data = temp_me 322 compat.link(context.scene, temp_ob) 323 try: 324 for vert in temp_me.vertices: 325 vert.co = deforms[vert.index].copy() 326 327 override = context.copy() 328 override['object'] = temp_ob 329 for index, mod in enumerate(temp_ob.modifiers): 330 if self.is_applies[index].value: 331 try: 332 bpy.ops.object.modifier_apply(override, modifier=mod.name) 333 except: 334 temp_ob.modifiers.remove(mod) 335 336 new_shape_deforms.append([v.co.copy() for v in temp_me.vertices]) 337 except Exception as e: 338 #ob.modifiers.remove(mod) 339 self.report(type={'WARNING'}, message=f_tip_("Could not apply '{}' modifier \"{}\" to shapekey {}", mod.type, mod.name, shape_index)) 340 print(f_("Error applying '{type}' modifier \"{name}\":\n\t", type=mod.type, name=mod.name), e) 341 finally: 342 common.remove_data(temp_ob) 343 common.remove_data(temp_me) 344 345 progress += 1 346 context.window_manager.progress_update(progress_start + progress / progress_count) 347 348 if ob.active_shape_key_index != 0: 349 ob.active_shape_key_index = 0 350 me.update() 351 352 copy_modifiers = ob.modifiers[:] 353 mod_count = len(copy_modifiers) 354 mod_progress = 0 355 override = context.copy() 356 override['object'] = ob 357 for index, mod in enumerate(copy_modifiers): 358 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 359 # break 360 if self.is_applies[index].value and (mod.type != 'ARMATURE' or not compat.IS_LEGACY): 361 if mod.type == 'MIRROR' and mod.use_mirror_vertex_groups: 362 if bpy.ops.object.decode_cm3d2_vertex_group_names.poll(): 363 self.report(type={'WARNING'}, message="Vertex groups are not in blender naming style. Mirror modifier results may not be as expected") 364 for vg in ob.vertex_groups[:]: 365 replace_list = ((r'\.L$', ".R"), (r'\.R$', ".L"), (r'\.l$', ".r"), (r'\.r$', ".l"), (r'_L$', "_R"), (r'_R$', "_L"), (r'_l$', "_r"), (r'_r$', "_l")) 366 for before, after in replace_list: 367 mirrored_name = re.sub(before, after, vg.name) 368 if mirrored_name not in ob.vertex_groups: 369 ob.vertex_groups.new(override, name=mirrored_name) 370 try: 371 bpy.ops.object.modifier_apply(override, modifier=mod.name) 372 except Exception as e: 373 #ob.modifiers.remove(mod) 374 self.report(type={'ERROR', 'WARNING'}, message=f_tip_("Could not apply '{type}' modifier \"{name}\"", type=mod.type, name=mod.name)) 375 print(f_("Error applying '{type}' modifier \"{name}\":\n\t", type=mod.type, name=mod.name), e) 376 377 mod_progress += 1 if (mod.type != 'ARMATURE' or not compat.IS_LEGACY) else 0 378 context.window_manager.progress_update( progress_start + (progress + mod_progress / mod_count) / progress_count ) 379 380 # Calculate custom normals for armature modifiers in legacy blender 381 if arm_ob: 382 bpy.ops.object.mode_set(mode='EDIT') 383 bpy.ops.object.mode_set(mode='OBJECT') 384 385 arm = arm_ob.data 386 arm_pose = arm_ob.pose 387 388 pose_quats = {} 389 for bone in arm.bones: 390 pose_bone = arm_pose.bones[bone.name] 391 392 bone_quat = bone.matrix_local.to_quaternion() 393 pose_quat = pose_bone.matrix.to_quaternion() 394 result_quat = compat.mul(pose_quat, bone_quat.inverted()) 395 396 pose_quats[bone.name] = result_quat.copy() 397 398 custom_normals = [] 399 for loop in me.loops: 400 vert = me.vertices[loop.vertex_index] 401 no = vert.normal.copy() 402 403 total_weight = 0.0 404 for vge in vert.groups: 405 vg = ob.vertex_groups[vge.group] 406 try: 407 pose_quats[vg.name] 408 except KeyError: 409 continue 410 total_weight += vge.weight 411 412 total_quat = mathutils.Quaternion() 413 if total_weight != 0.0: 414 for vge in vert.groups: 415 vg = ob.vertex_groups[vge.group] 416 try: 417 total_quat = total_quat.slerp(pose_quats[vg.name], vge.weight / total_weight) 418 except KeyError: 419 pass 420 421 no.rotate(total_quat) 422 custom_normals.append(no) 423 424 progress += 1 425 context.window_manager.progress_update(progress_start + progress / progress_count) 426 427 override = context.copy() 428 override['object'] = ob 429 for index, mod in enumerate(copy_modifiers): 430 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 431 # break 432 if self.is_applies[index].value and (mod.type == 'ARMATURE' and compat.IS_LEGACY): 433 try: 434 bpy.ops.object.modifier_apply(override, modifier=mod.name) 435 except Exception as e: 436 #ob.modifiers.remove(mod) 437 self.report(type={'ERROR', 'WARNING'}, message=f_tip_("Could not apply '{mod_type}' modifier \"{mod_name}\"", mod_type=mod.type, mod_name=mod.name) ) 438 print(f_("Could not apply '{mod_type}' modifier \"{mod_name}\":\n\t", mod_type=mod.type, mod_name=mod.name), e) 439 440 mod_progress += 1 if (mod.type == 'ARMATURE' and compat.IS_LEGACY) else 0 441 context.window_manager.progress_update( progress_start + (progress + mod_progress / mod_count) / progress_count ) 442 443 progress += 1 444 context.window_manager.progress_update(progress_start + progress / progress_count) 445 446 compat.set_active(context, ob) 447 448 if is_shaped: 449 for deforms in new_shape_deforms: 450 if len(me.vertices) != len(deforms): 451 self.report(type={'ERROR'}, message="ミラー等が原因で頂点数が変わっているためシェイプキーを格納できません、中止するのでCtrl+Z等で元に戻し修正してください。") 452 context.window_manager.progress_update(progress_start + 1) 453 if did_start_progress: 454 context.window_manager.progress_end() 455 return {'FINISHED', 'CANCELLED'} 456 457 for shape_index, deforms in enumerate(new_shape_deforms): 458 bpy.ops.object.shape_key_add(context.copy(), from_mix=False) 459 shape = ob.active_shape_key 460 shape.name = shape_names[shape_index] 461 462 for vert in me.vertices: 463 shape.data[vert.index].co = deforms[vert.index].copy() 464 465 progress += 1 466 context.window_manager.progress_update(progress_start + progress / progress_count) 467 468 for shape_index, shape in enumerate(me.shape_keys.key_blocks): 469 shape.relative_key = me.shape_keys.key_blocks[pre_relative_keys[shape_index]] 470 if self.is_preserve_shape_key_values: 471 shape.value = pre_shape_key_values[shape_index] 472 473 ob.active_shape_key_index = pre_active_shape_key_index 474 475 for temp_ob in pre_selected_objects: 476 compat.set_select(temp_ob, True) 477 bpy.ops.object.mode_set(mode=pre_mode) 478 479 if arm_ob: 480 for i, loop in enumerate(me.loops): 481 vert = me.vertices[loop.vertex_index] 482 no = vert.normal.copy() 483 484 try: 485 custom_rot = mathutils.Vector((0.0, 0.0, 1.0)).rotation_difference(custom_normals[i]) 486 except: 487 continue 488 original_rot = mathutils.Vector((0.0, 0.0, 1.0)).rotation_difference(no) 489 output_rot = original_rot.slerp(custom_rot, custom_normal_blend) 490 491 output_no = mathutils.Vector((0.0, 0.0, 1.0)) 492 output_no.rotate(output_rot) 493 494 custom_normals[i] = output_no 495 me.use_auto_smooth = True 496 me.normals_split_custom_set(custom_normals) 497 498 progress += 1 499 context.window_manager.progress_update(progress_start + progress / progress_count) 500 501 context.window_manager.progress_update(progress_start + 1) 502 if did_start_progress: 503 context.window_manager.progress_end() 504 return {'FINISHED'}
is_preserve_shape_key_values: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Preserve Shape Key Values', 'default': True, 'description': 'Ensure shape key values are not changed', 'attr': 'is_preserve_shape_key_values'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Preserve Shape Key Values', 'default': True, 'description': 'Ensure shape key values are not changed', 'attr': 'is_preserve_shape_key_values'}>
is_applies: <_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.common.CNV_SelectorItem'>, 'attr': 'is_applies'}> =
<_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.common.CNV_SelectorItem'>, 'attr': 'is_applies'}>
active_modifier: <_PropertyDeferred, <built-in function IntProperty>, {'name': 'Active Modifier', 'attr': 'active_modifier'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'name': 'Active Modifier', 'attr': 'active_modifier'}>
apply_viewport_visible: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Apply Viewport-Visible Modifiers', 'default': False, 'attr': 'apply_viewport_visible'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Apply Viewport-Visible Modifiers', 'default': False, 'attr': 'apply_viewport_visible'}>
apply_renderer_visible: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Apply Renderer-Visible Modifiers', 'default': False, 'attr': 'apply_renderer_visible'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Apply Renderer-Visible Modifiers', 'default': False, 'attr': 'apply_renderer_visible'}>
initial_progress: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Progress', 'default': -1, 'options': {'HIDDEN', 'SKIP_SAVE'}, 'attr': 'initial_progress'}> =
<_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Progress', 'default': -1, 'options': {'HIDDEN', 'SKIP_SAVE'}, 'attr': 'initial_progress'}>
def
invoke(self, context, event):
187 def invoke(self, context, event): 188 ob = context.active_object 189 if len(ob.modifiers) == 0: 190 return {'CANCELLED'} 191 192 for index, mod in enumerate(ob.modifiers): 193 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 194 # self.report(type={'WARNING'}, message="Can only apply the first 32 modifiers at once.") 195 # break 196 icon = 'MOD_%s' % mod.type.replace('DECIMATE','DECIM').replace('SOFT_BODY','SOFT').replace('PARTICLE_SYSTEM','PARTICLES').replace('_SPLIT','SPLIT').replace('_PROJECT','PROJECT').replace('_DEFORM','DEFORM').replace('_SIMULATION','SIM').replace('_EDIT','').replace('_MIX','').replace('_PROXIMITY','').replace('_PAINT','PAINT') 197 icon = compat.icon(icon) 198 199 new_prop = None 200 if index < len(self.is_applies): 201 new_prop = self.is_applies[index] 202 else: 203 new_prop = self.is_applies.add() 204 205 if new_prop.name == mod.name and new_prop.icon == icon: 206 # It's probably the same one, ignore it 207 pass 208 else: 209 new_prop.name = mod.name 210 new_prop.index = index 211 new_prop.value = mod.show_viewport 212 new_prop.preferred = new_prop.value 213 new_prop.icon = icon 214 new_prop.filter0 = mod.show_viewport 215 new_prop.filter1 = mod.show_render 216 217 while len(self.is_applies) > len(ob.modifiers): 218 self.is_applies.remove(len(self.is_applies)-1) 219 220 return context.window_manager.invoke_props_dialog(self)
def
draw(self, context):
222 def draw(self, context): 223 prefs = common.preferences() 224 if compat.IS_LEGACY: 225 self.layout.prop(prefs, 'custom_normal_blend' , icon=compat.icon('SNAP_NORMAL' ), slider=True) 226 self.layout.prop(self , 'is_preserve_shape_key_values', icon=compat.icon('SHAPEKEY_DATA'), slider=True) 227 self.layout.label(text="適用するモディファイア") 228 ob = context.active_object 229 230 #for index, mod in enumerate(ob.modifiers): 231 # if index >= 32: # luvoid : can only apply 32 modifiers at once. 232 # break 233 # icon = 'MOD_%s' % mod.type.replace('DECIMATE','DECIM').replace('SOFT_BODY','SOFT').replace('PARTICLE_SYSTEM','PARTICLES').replace('_SPLIT','SPLIT').replace('_PROJECT','PROJECT').replace('_DEFORM','DEFORM').replace('_SIMULATION','SIM').replace('_EDIT','').replace('_MIX','').replace('_PROXIMITY','').replace('_PAINT','PAINT') 234 # try: 235 # self.layout.prop(self, 'is_applies', text=mod.name, index=index, icon=icon) 236 # except: 237 # self.layout.prop(self, 'is_applies', text=mod.name, index=index, icon='MODIFIER') 238 239 self.layout.template_list("CNV_UL_modifier_selector", "", self, "is_applies", self, "active_modifier") 240 self.layout.label(text="Show filters", icon='FILE_PARENT')
def
execute(self, context):
242 def execute(self, context): 243 ob = context.object 244 245 did_start_progress = False 246 if self.initial_progress == -1: 247 progress_start = 0 248 context.window_manager.progress_begin(0, 1) 249 did_start_progress = True 250 else: 251 progress_start = self.initial_progress 252 253 if self.apply_viewport_visible or self.apply_renderer_visible: 254 for index, mod in enumerate(ob.modifiers): 255 new_prop = None 256 if index < len(self.is_applies): 257 new_prop = self.is_applies[index] 258 else: 259 new_prop = self.is_applies.add() 260 261 new_prop.name = mod.name 262 new_prop.index = index 263 new_prop.value = (self.apply_viewport_visible and mod.show_viewport) or (self.apply_renderer_visible and mod.show_render) 264 265 # 対象が一つも無い場合はキャンセル扱いとする 266 is_any = False 267 for item in self.is_applies: 268 if item.value: 269 is_any = True 270 break 271 if not is_any: 272 self.report(type={'INFO'}, message="適用対象のモディファイアがないため、キャンセルします") 273 context.window_manager.progress_update(progress_start + 1) 274 if did_start_progress: 275 context.window_manager.progress_end() 276 return {'CANCELLED'} 277 278 custom_normal_blend = common.preferences().custom_normal_blend 279 bpy.ops.object.mode_set(mode='OBJECT') 280 281 me = ob.data 282 is_shaped = bool(me.shape_keys) 283 284 pre_selected_objects = context.selected_objects[:] 285 pre_mode = ob.mode 286 287 arm_ob = None 288 if compat.IS_LEGACY: 289 for mod in ob.modifiers: 290 if mod.type == "ARMATURE": 291 arm_ob = mod.object 292 293 progress = 0 294 progress_count = 1 295 progress_count += 2 if arm_ob else 0 296 progress_count += len(me.shape_keys.key_blocks) * 3 if is_shaped else 0 297 298 if is_shaped: 299 pre_active_shape_key_index = ob.active_shape_key_index 300 pre_relative_keys = [None] * len(me.shape_keys.key_blocks) 301 pre_shape_key_values = [0] * len(me.shape_keys.key_blocks) 302 shape_names = [""] * len(me.shape_keys.key_blocks) 303 shape_deforms = [None] * len(me.shape_keys.key_blocks) 304 for shape_index, shape in enumerate(me.shape_keys.key_blocks): 305 pre_relative_keys [shape_index] = shape.relative_key.name 306 pre_shape_key_values[shape_index] = shape.value 307 shape_names [shape_index] = shape.name 308 shape_deforms [shape_index] = [shape.data[v.index].co.copy() for v in me.vertices] 309 310 progress += 1 311 context.window_manager.progress_update(progress_start + progress / progress_count) 312 313 ob.active_shape_key_index = len(me.shape_keys.key_blocks) - 1 314 for i in me.shape_keys.key_blocks[:]: 315 ob.shape_key_remove(ob.active_shape_key) 316 317 new_shape_deforms = [] 318 for shape_index, deforms in enumerate(shape_deforms): 319 temp_ob = ob.copy() 320 temp_me = me.copy() 321 temp_ob.data = temp_me 322 compat.link(context.scene, temp_ob) 323 try: 324 for vert in temp_me.vertices: 325 vert.co = deforms[vert.index].copy() 326 327 override = context.copy() 328 override['object'] = temp_ob 329 for index, mod in enumerate(temp_ob.modifiers): 330 if self.is_applies[index].value: 331 try: 332 bpy.ops.object.modifier_apply(override, modifier=mod.name) 333 except: 334 temp_ob.modifiers.remove(mod) 335 336 new_shape_deforms.append([v.co.copy() for v in temp_me.vertices]) 337 except Exception as e: 338 #ob.modifiers.remove(mod) 339 self.report(type={'WARNING'}, message=f_tip_("Could not apply '{}' modifier \"{}\" to shapekey {}", mod.type, mod.name, shape_index)) 340 print(f_("Error applying '{type}' modifier \"{name}\":\n\t", type=mod.type, name=mod.name), e) 341 finally: 342 common.remove_data(temp_ob) 343 common.remove_data(temp_me) 344 345 progress += 1 346 context.window_manager.progress_update(progress_start + progress / progress_count) 347 348 if ob.active_shape_key_index != 0: 349 ob.active_shape_key_index = 0 350 me.update() 351 352 copy_modifiers = ob.modifiers[:] 353 mod_count = len(copy_modifiers) 354 mod_progress = 0 355 override = context.copy() 356 override['object'] = ob 357 for index, mod in enumerate(copy_modifiers): 358 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 359 # break 360 if self.is_applies[index].value and (mod.type != 'ARMATURE' or not compat.IS_LEGACY): 361 if mod.type == 'MIRROR' and mod.use_mirror_vertex_groups: 362 if bpy.ops.object.decode_cm3d2_vertex_group_names.poll(): 363 self.report(type={'WARNING'}, message="Vertex groups are not in blender naming style. Mirror modifier results may not be as expected") 364 for vg in ob.vertex_groups[:]: 365 replace_list = ((r'\.L$', ".R"), (r'\.R$', ".L"), (r'\.l$', ".r"), (r'\.r$', ".l"), (r'_L$', "_R"), (r'_R$', "_L"), (r'_l$', "_r"), (r'_r$', "_l")) 366 for before, after in replace_list: 367 mirrored_name = re.sub(before, after, vg.name) 368 if mirrored_name not in ob.vertex_groups: 369 ob.vertex_groups.new(override, name=mirrored_name) 370 try: 371 bpy.ops.object.modifier_apply(override, modifier=mod.name) 372 except Exception as e: 373 #ob.modifiers.remove(mod) 374 self.report(type={'ERROR', 'WARNING'}, message=f_tip_("Could not apply '{type}' modifier \"{name}\"", type=mod.type, name=mod.name)) 375 print(f_("Error applying '{type}' modifier \"{name}\":\n\t", type=mod.type, name=mod.name), e) 376 377 mod_progress += 1 if (mod.type != 'ARMATURE' or not compat.IS_LEGACY) else 0 378 context.window_manager.progress_update( progress_start + (progress + mod_progress / mod_count) / progress_count ) 379 380 # Calculate custom normals for armature modifiers in legacy blender 381 if arm_ob: 382 bpy.ops.object.mode_set(mode='EDIT') 383 bpy.ops.object.mode_set(mode='OBJECT') 384 385 arm = arm_ob.data 386 arm_pose = arm_ob.pose 387 388 pose_quats = {} 389 for bone in arm.bones: 390 pose_bone = arm_pose.bones[bone.name] 391 392 bone_quat = bone.matrix_local.to_quaternion() 393 pose_quat = pose_bone.matrix.to_quaternion() 394 result_quat = compat.mul(pose_quat, bone_quat.inverted()) 395 396 pose_quats[bone.name] = result_quat.copy() 397 398 custom_normals = [] 399 for loop in me.loops: 400 vert = me.vertices[loop.vertex_index] 401 no = vert.normal.copy() 402 403 total_weight = 0.0 404 for vge in vert.groups: 405 vg = ob.vertex_groups[vge.group] 406 try: 407 pose_quats[vg.name] 408 except KeyError: 409 continue 410 total_weight += vge.weight 411 412 total_quat = mathutils.Quaternion() 413 if total_weight != 0.0: 414 for vge in vert.groups: 415 vg = ob.vertex_groups[vge.group] 416 try: 417 total_quat = total_quat.slerp(pose_quats[vg.name], vge.weight / total_weight) 418 except KeyError: 419 pass 420 421 no.rotate(total_quat) 422 custom_normals.append(no) 423 424 progress += 1 425 context.window_manager.progress_update(progress_start + progress / progress_count) 426 427 override = context.copy() 428 override['object'] = ob 429 for index, mod in enumerate(copy_modifiers): 430 #if index >= 32: # luvoid : can only apply 32 modifiers at once. 431 # break 432 if self.is_applies[index].value and (mod.type == 'ARMATURE' and compat.IS_LEGACY): 433 try: 434 bpy.ops.object.modifier_apply(override, modifier=mod.name) 435 except Exception as e: 436 #ob.modifiers.remove(mod) 437 self.report(type={'ERROR', 'WARNING'}, message=f_tip_("Could not apply '{mod_type}' modifier \"{mod_name}\"", mod_type=mod.type, mod_name=mod.name) ) 438 print(f_("Could not apply '{mod_type}' modifier \"{mod_name}\":\n\t", mod_type=mod.type, mod_name=mod.name), e) 439 440 mod_progress += 1 if (mod.type == 'ARMATURE' and compat.IS_LEGACY) else 0 441 context.window_manager.progress_update( progress_start + (progress + mod_progress / mod_count) / progress_count ) 442 443 progress += 1 444 context.window_manager.progress_update(progress_start + progress / progress_count) 445 446 compat.set_active(context, ob) 447 448 if is_shaped: 449 for deforms in new_shape_deforms: 450 if len(me.vertices) != len(deforms): 451 self.report(type={'ERROR'}, message="ミラー等が原因で頂点数が変わっているためシェイプキーを格納できません、中止するのでCtrl+Z等で元に戻し修正してください。") 452 context.window_manager.progress_update(progress_start + 1) 453 if did_start_progress: 454 context.window_manager.progress_end() 455 return {'FINISHED', 'CANCELLED'} 456 457 for shape_index, deforms in enumerate(new_shape_deforms): 458 bpy.ops.object.shape_key_add(context.copy(), from_mix=False) 459 shape = ob.active_shape_key 460 shape.name = shape_names[shape_index] 461 462 for vert in me.vertices: 463 shape.data[vert.index].co = deforms[vert.index].copy() 464 465 progress += 1 466 context.window_manager.progress_update(progress_start + progress / progress_count) 467 468 for shape_index, shape in enumerate(me.shape_keys.key_blocks): 469 shape.relative_key = me.shape_keys.key_blocks[pre_relative_keys[shape_index]] 470 if self.is_preserve_shape_key_values: 471 shape.value = pre_shape_key_values[shape_index] 472 473 ob.active_shape_key_index = pre_active_shape_key_index 474 475 for temp_ob in pre_selected_objects: 476 compat.set_select(temp_ob, True) 477 bpy.ops.object.mode_set(mode=pre_mode) 478 479 if arm_ob: 480 for i, loop in enumerate(me.loops): 481 vert = me.vertices[loop.vertex_index] 482 no = vert.normal.copy() 483 484 try: 485 custom_rot = mathutils.Vector((0.0, 0.0, 1.0)).rotation_difference(custom_normals[i]) 486 except: 487 continue 488 original_rot = mathutils.Vector((0.0, 0.0, 1.0)).rotation_difference(no) 489 output_rot = original_rot.slerp(custom_rot, custom_normal_blend) 490 491 output_no = mathutils.Vector((0.0, 0.0, 1.0)) 492 output_no.rotate(output_rot) 493 494 custom_normals[i] = output_no 495 me.use_auto_smooth = True 496 me.normals_split_custom_set(custom_normals) 497 498 progress += 1 499 context.window_manager.progress_update(progress_start + progress / progress_count) 500 501 context.window_manager.progress_update(progress_start + 1) 502 if did_start_progress: 503 context.window_manager.progress_end() 504 return {'FINISHED'}
Inherited Members
- bpy_types.Operator
- as_keywords
- poll_message_set
- builtins.bpy_struct
- keys
- values
- items
- get
- pop
- as_pointer
- keyframe_insert
- keyframe_delete
- driver_add
- driver_remove
- is_property_set
- property_unset
- is_property_readonly
- is_property_overridable_library
- property_overridable_library_set
- path_resolve
- path_from_id
- type_recast
- bl_rna_get_subclass_py
- bl_rna_get_subclass
- id_properties_ensure
- id_properties_clear
- id_properties_ui
- id_data